/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */
import fse from 'fs-extra';
import path from 'path';
import process from 'process';

import { getExtraConfig } from '../../base/data/extra-config.js';
import { HvigorLogger } from '../../base/log/hvigor-log.js';
import { BUILD_CACHE_DIR, HVIGOR_CACHE_DIR_KEY, HVIGOR_USER_HOME_DIR_NAME } from '../const/const.js';
import { HVIGOR_PROJECT_ROOT_DIR } from '../const/path-const.js';

import { HvigorConfigLoader } from './hvigor-config-loader.js';

export class PathUtil {
  // 设置本util中日志最多打印几次
  private static hvigorCacheDirHasLogged = false;

  /**
   * 获取.hvigor的根目录，就是编译时产生的.hvigor文件夹，不是userHome下的
   * 例如D:\test\ToDoListArkTS\.hvigor
   * 会先从项目的配置文件中获取，不存在则获取userHome目录下的配置文件，都不存在返回项目下的
   */
  public static getHvigorCacheDir(logger?: HvigorLogger): string {
    let hvigorCacheDir: string | undefined =
      process.env.config !== undefined
        ? JSON.parse(process.env.config)[BUILD_CACHE_DIR]
        : getExtraConfig(BUILD_CACHE_DIR) ?? PathUtil.getCommandHvigorCacheDir();
    const defaultDir = path.resolve(HVIGOR_PROJECT_ROOT_DIR, HVIGOR_USER_HOME_DIR_NAME);
    if (!hvigorCacheDir) {
      hvigorCacheDir = HvigorConfigLoader.getInstance().getPropertiesConfigValue<string>(HVIGOR_CACHE_DIR_KEY);
      if (!hvigorCacheDir) {
        return defaultDir;
      }
    }

    if (!path.isAbsolute(hvigorCacheDir)) {
      if (logger && !this.hvigorCacheDirHasLogged) {
        logger.warn(`Invalid custom hvigor data dir:${hvigorCacheDir}`);
        this.hvigorCacheDirHasLogged = true;
      }
      return defaultDir;
    }

    if (logger && !this.hvigorCacheDirHasLogged) {
      logger.warn('Please ensure no projects of the same name have the same custom hvigor data dir.');
      this.hvigorCacheDirHasLogged = true;
    }

    return path.resolve(hvigorCacheDir, path.basename(process.cwd()), HVIGOR_USER_HOME_DIR_NAME);
  }

  /**
   *
   * 检查用来copy的两个路径是否是指向相同的路径
   *
   * @param src
   * @param dest
   * @return 相同路径返回true,不同路径返回false
   */
  public static checkCopyPathIsSame(src: string, dest: string): boolean {
    const srcStat = PathUtil.getStatsSync(src);
    const destStat = PathUtil.getStatsSync(dest);

    // 两个文件都存在的情况下才能判断,任意有一个不存在则必定不指向同一个路径，src不存在无法copy
    return destStat && srcStat ? !!PathUtil.areIdentical(srcStat, destStat) : false;
  }

  /**
   *
   * 获取一个文件的stats
   * @param path
   * @private
   * @return 返回fse.Stats对象，文件不能读取(不存在或其他报错)返回null
   */
  public static getStatsSync(path: string): fse.Stats | null {
    let pathStat;
    try {
      pathStat = fse.statSync(path);
    } catch (err) {
      return null;
    }
    return pathStat;
  }

  private static areIdentical(srcStat: fse.Stats, destStat: fse.Stats) {
    return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev;
  }

  private static getCommandHvigorCacheDir() {
    const argv = process.argv;
    argv.forEach((it) => {
      if (it.startsWith(BUILD_CACHE_DIR)) {
        process.env.BUILD_CACHE_DIR = it.substring(it.indexOf('=') + 1);
      }
    });
    return process.env.BUILD_CACHE_DIR;
  }

  public static getReportDirPath(): string {
    return path.resolve(PathUtil.getHvigorCacheDir(), 'report');
  }
}
